Skip to content

Fix stale request cache, auth resets, and download() error/session handling - #2994

Open
consciousmediacm-dev wants to merge 1 commit into
ranaroussi:devfrom
consciousmediacm-dev:claude/amazing-curie-1rbgwo
Open

consciousmediacm-dev wants to merge 1 commit into
ranaroussi:devfrom
consciousmediacm-dev:claude/amazing-curie-1rbgwo

Conversation

@consciousmediacm-dev

Copy link
Copy Markdown

Summary
Six reliability fixes, mostly affecting long-running processes and multi-ticker download(). Each has an offline regression test in tests/test_reliability_fixes.py.

Bug Fix

1 YfData.cache_get() uses lru_cache with no expiry, so in a long-running process e.g. Market("US").summary, Search, and fundamentals return the first response forever Bounded cache with TTL yf.config.network.cache_ttl (default 60s; 0 disables, None never expires). Error responses are not cached. Adds YfData.cache_clear(). Documented in doc/source/advanced/config.rst
2 Any HTTP >= 400, including 404 for a delisted/mistyped ticker, toggles the cookie strategy and wipes the crumb shared by all threads (one bad ticker caused 7 requests in a mocked trace) 404 no longer triggers the cookie-strategy retry; 401 etc. still do
3 download() toggles config.network.hide_exceptions, a key nothing reads (debug.hide_exceptions is the real one). Fixing just the name would race between threads _download_one calls PriceHistory._history(raise_errors=True) per call; global config untouched. Public history(raise_errors=...) keeps its deprecation warning
4 Every download() without session= creates a new session and swaps it into the YfData singleton, keeping the old crumb with an empty cookie jar Only swap when a session is passed; _set_session resets cookie/crumb when the session object changes
5 Tickers.download() assigns results to an unused _history attribute (with a {} fallback that would raise) Removed
6 With the basic strategy, _get_cookie_basic never sets self._cookie, so fc.yahoo.com is re-requested on every call whenever the persistent cookie cache is unusable (read-only cache dir, multiple Yahoo cookies) Set self._cookie = True after a successful fetch, as the csrf path already does
Behaviour changes to note
Inside download(), per-ticker history errors now raise into the collector as the original code intended. A soft failure such as auto_adjust failing yields an empty frame plus one grouped error log for that ticker, instead of unadjusted data plus a duplicate per-ticker log line.
Historical-range chart requests previously cached forever; they now refetch after cache_ttl (set None to restore the old behaviour).
Testing
New tests: 21 pass. Against unmodified dev, 16 fail (they catch the bugs) and 5 pass (guards for behaviour that must not change, e.g. a 401 still retries).
python -m unittest tests.test_reliability_fixes: OK.
Offline suite (http, data, cookie/crumb degradation, download concurrency, utils, auth, live, screener, multi): 100 passed. 1 failure is environmental: US/Eastern missing from the test machine's tzdata, identical without this change.
Network-dependent suites couldn't reach Yahoo from the development machine; results were identical with and without this change.
ruff check clean.
Separately exercised against live Yahoo through a downstream wrapper (quotes, daily/intraday history, financials, info, bad-ticker handling): all passed.

Claude-Session: https://claude.ai/code/session_01VxuCGhah3SL3ZWQrwXUQDR

…ndling

- cache_get(): replace the never-expiring lru_cache with a bounded cache
  whose entries expire after yf.config.network.cache_ttl seconds (default
  60; 0 disables, None never expires). Error responses are not cached.
  Adds YfData.cache_clear().
- _make_request(): a 404 (delisted/mistyped ticker) no longer switches
  cookie strategy and wipes the crumb shared by all threads.
- _get_cookie_basic(): mark the cookie as fetched, so fc.yahoo.com isn't
  re-requested on every call when the persistent cookie cache is unusable.
- _set_session(): reset cookie/crumb when the session object changes.
- download(): only replace the shared session when the caller passes one;
  request exceptions per call via PriceHistory._history(raise_errors=True)
  instead of toggling a config key nobody read (network.hide_exceptions),
  which would also have raced between threads.
- Tickers.download(): drop dead assignment to an unused _history attribute.
- Add offline regression tests (tests/test_reliability_fixes.py) and
  document cache_ttl.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VxuCGhah3SL3ZWQrwXUQDR
@ValueRaider

Copy link
Copy Markdown
Collaborator

Can these be separated into individual PRs?

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants